/**
 * Copyright 2006 gworks.com.au
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. (http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 *
 * <dhamma-message src="Atisha (11th century Tibetan Buddhist master)">
 * 	The greatest achievement is selflessness. The greatest worth is self-mastery.
 * 	The greatest quality is seeking to serve others. The greatest precept is continual awareness.
 * 	The greatest medicine is the emptiness of everything. The greatest action is not conforming with the worlds ways.
 * 	The greatest magic is transmuting the passions. The greatest generosity is non-attachment.
 * 	The greatest goodness is a peaceful mind. The greatest patience is humility.
 * 	The greatest effort is not concerned with results. The greatest meditation is a mind that lets go.
 * 	The greatest wisdom is seeing through appearances. 
 * </dhamma-message>
 */
package au.com.gworks.jump.app.util;

import java.io.IOException;
import java.util.StringTokenizer;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.javaongems.runtime.http.ExpressRedirector;
import org.javaongems.runtime.lang.StringUtils;
import org.javaongems.server.PrincipalUtils;

import au.com.gworks.jump.io.SystemFailure;
import au.com.gworks.jump.system.ApplicationManager;


public class RequestInterceptor implements Filter {
	final static public String PLUGIN_PARAM = "plugin-class";
	final static private Logger LOGGER = Logger.getLogger(RequestInterceptor.class);
	
	private RequestInterceptorPlugin plugin;
    
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
		if (req instanceof HttpServletRequest) {
			EnvironmentUtils.initializeCharacterEncoding((HttpServletRequest) req);
			initialiseEnvironmentForRequest((HttpServletRequest)req, res, chain);
		}
	}

	private void initialiseEnvironmentForRequest(HttpServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
		boolean[] more = new boolean[1];
		String pathInfo = req.getPathInfo();
		boolean[] namespaceInPathInfo = new boolean[1];
		String namespace = getNamespace(pathInfo, more, namespaceInPathInfo);
		req.setAttribute(EnvironmentUtils.ENV_NAMESPACE, namespace);
		req.setAttribute(EnvironmentUtils.ENV_WAS_NAMESPACE_SPECIFIED, new Boolean(namespaceInPathInfo[0]));
		plugin.openRepository(namespace, PrincipalUtils.getPrincipal(req));
		try {
			String repNamespace = plugin.getRepositoryNamespace();
			if (!namespace.equals(repNamespace))
				req.setAttribute(EnvironmentUtils.ENV_ORIGINAL_PATH_INFO, pathInfo);
			try {
				EnvironmentUtils.initialiseVisitationContext((HttpServletRequest) req, (HttpServletResponse) res, plugin);				
			} catch (ExpressRedirector.ShortCircuit err) {
				return;
			}
			chain.doFilter(req, res);
		} finally {
			plugin.closeRepository();
		}
	}
	
	static private String getNamespace(String pathInfo, boolean[] moreElements, boolean[] namespaceInPathInfo) {
		String ret = ApplicationManager.getDefaultEntryNamespace();
		namespaceInPathInfo[0] = false;
		moreElements[0] = false;
		if (StringUtils.isEmpty(pathInfo))
			pathInfo = "/";
		StringTokenizer tok = new StringTokenizer(pathInfo,"/");
		if (tok.hasMoreTokens()) { 
			ret = tok.nextToken();
			namespaceInPathInfo[0] = true;
			moreElements[0] = tok.hasMoreElements();
		} 
		if (LOGGER.isDebugEnabled()) LOGGER.debug("request manager filter using ns:" + ret);
		return ret;
	}
	
	public void init(FilterConfig filterConfig) {
		String pluginName = filterConfig.getInitParameter(PLUGIN_PARAM);
		if (StringUtils.isEmpty(pluginName))
			throw new SystemFailure(LOGGER, "a valid request manager filter plugin is required to wrap all requests", new IllegalStateException("invalid plugin"));
		try {
			Class pluginClz = Class.forName(pluginName);
			plugin = (RequestInterceptorPlugin) pluginClz.newInstance();
		} catch (Exception err) {
			throw new SystemFailure(LOGGER, "error initialising request manager filter plugin", err);
		}
		plugin.init(filterConfig);
	}

	public void destroy() {
		// nothing to do.
	}
}